// Copyright 2011, Vanya Davidenko.
// Кодировка файла: UTF-8. 
package info.iu9.red;



class ForwardStringIterator extends StringIterator {
  ForwardStringIterator() {
    this("");
  }

  ForwardStringIterator(final String string) {
    this(string, 0, string.length());
  }


  ForwardStringIterator(final String string, final int begin, final int end) {
    reset(string, begin, end);
  }


  protected boolean checkBounds(final String string,
                                final int begin, final int end) {
    return 0 <= begin && begin <= end && end <= string.length();
  }

  protected void concreteReset() {
    set_index(begin());
    set_current_char_length(0);
  }

  public int next() {
    // Обработка конца строки исключение здесь оправдана, так как он
    // будет достигнут один раз и, соответственно, исключение будет
    // сгенерировано только 1 раз, а проверять через if каждый раз — двойная
    // работа, ибо charAt все равно сделает такую же проверку.
    // Поэтому обработка исключения здесь — преобразование интерфейса charAt.

    set_index(index() + current_char_length());

    if ( index() == end() ) {
      set_current_char_length(0);
      return EOL;
    }

    final char h;
    try {
      h = string().charAt(index());
    } catch(StringIndexOutOfBoundsException e) {
      set_current_char_length(0);
      return EOL;
    }

    // В случае битого суррогата данный участок кода сгенерирует исключение.
    if ( Character.isHighSurrogate(h) ) {
      set_current_char_length(2);
      return Character.toCodePoint(h, string().charAt(index() + 1));
    } else {
      set_current_char_length(1);
      return h;
    }
  }

  public boolean isStringBegin() {
    return index() == 0;
  }
  public boolean isStringEnd() {
    return index() == string().length();
  }
  protected boolean nextIsStringEnd() {
    return nextIndex() == string().length();
  }

  protected int prevIndex() {
    // При объединении двух проверок скорость падает на 10%, вероятно,
    // сказывается работа HotSpot.
    if ( index() == 0 ) {
      return -1;
    }
    if ( Character.isLowSurrogate(string().charAt(index() - 1)) ) {
      return index() - 2;
    }
    return index() - 1;
  }
  protected int nextIndex() {
    return index() + current_char_length();
  }
}
